﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Marmat.Forms
{
    /// <summary>
    /// 表示 多选组合框控件。
    /// </summary>
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(System.Windows.Forms.ComboBox))]
    public partial class CheckedComboBox : DropDownBox
    {

        /// <summary>
        /// 初始化 Marmat.Forms.CheckedComboBox 类的新实例。
        /// </summary>
        public CheckedComboBox()
        {

            // 此调用是设计器所必需的。
            this.InitializeComponent();

            // 在 InitializeComponent() 调用之后添加任何初始化。
            this.ShowModalButton = false;
            this.AllowEdit = false;
            base.PopupControl = new CheckedComboBoxForm();
            this.TextEdit1.Properties.PopupSizeable = false;
            this.TextEdit1.Properties.ShowPopupCloseButton = false;
            this.TextEdit1.Properties.ShowPopupShadow = false;
            base.TextEditStyle = TextEditStyles.DisableTextEditor;
        }

        private CheckedComboBoxForm Form
        {
            get => (CheckedComboBoxForm)base.PopupControl;
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override bool ShowModalButton
        {
            get => base.ShowModalButton;
            set => base.ShowModalButton = value;
        }

        /// <summary>
        /// 获取包含在集合中的元素数量。
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [Browsable(false)]
        public int ItemCount
        {
            get => this.Form.CheckedListBoxControl1.ItemCount;
        }

        /// <summary>
        /// 更新中(相当于一个开关，用于更新值，却不促发部分事件，避免死循环。)
        /// </summary>
        /// <remarks></remarks>
        private bool Updating = false;

        /// <summary>
        /// 获取或设置控件的文本编辑风格。
        /// </summary>
        [DefaultValue(typeof(TextEditStyles), "DisableTextEditor")]
        public override TextEditStyles TextEditStyle
        {
            get => base.TextEditStyle;
            set => base.TextEditStyle = value;
        }

        /// <summary>
        /// 获取或设置控件的分隔符字符
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [DefaultValue(typeof(char), ",")]
        public char SeparatorChar
        {
            get => this.m_SeparatorChar;
            set => this.m_SeparatorChar = value;
        }

        private char m_SeparatorChar = ',';

        /// <summary>
        /// 获取或设置此控件的数据源。
        /// </summary>
        public override object DataSource
        {
            get => base.DataSource;
            set
            {
                base.DataSource = value;
                this.Form.CheckedListBoxControl1.DataSource = value;
            }
        }

        public override string DisplayMember
        {
            get => base.DisplayMember;
            set
            {
                base.DisplayMember = value;
                this.Form.CheckedListBoxControl1.DisplayMember = value;
            }
        }

        public override string ValueMember
        {
            get => base.ValueMember;
            set
            {
                base.ValueMember = value;
                this.Form.CheckedListBoxControl1.ValueMember = value;
            }
        }

        /// <summary>
        /// 获取一个对象，该对象表示该  Marmat.Forms.BCheckedComboBox 中所包含项的集合
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [Bindable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("数据")]
        [Description("获取一个对象，该对象表示该  Marmat.Forms.BCheckedComboBox 中所包含项的集合。")]
        public ComboBox.ItemCollection Items
        {
            get
            {
                if (this.m_Items is null)
                    this.m_Items = new ComboBox.ItemCollection(this.Form.CheckedListBoxControl1.Items);
                return this.m_Items;
            }
        }

        private ComboBox.ItemCollection m_Items;

        /// <summary>
        /// 获取或设置组合框中项的高度。
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [DefaultValue(20)]
        [Category("外观")]
        [Description("获取或设置组合框中项的高度。")]
        public int ItemHeight
        {
            get => this.Form.CheckedListBoxControl1.ItemHeight;
            set => this.Form.CheckedListBoxControl1.ItemHeight = value;
        }

        /// <summary>
        /// 打开下拉窗体前触发，用于更新已选择的项，及下拉窗体的尺寸
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BComboBox_DropDownFormOpening(object sender, CancelEventArgs e)
        {
            if (base.PopupControl is object && base.PopupControl.IsDisposed == false)
            {
                CheckedComboBoxForm PopupControl = this.Form;
                PopupControl.CheckedListBoxControl1.UnCheckAll();
                foreach (object item in this.SelectedItems)
                {
                    for (int i = 0, loopTo = PopupControl.CheckedListBoxControl1.ItemCount - 1; i <= loopTo; i++)
                    {
                        var itemValue = PopupControl.CheckedListBoxControl1.GetItemValue(i);
                        if (itemValue.Equals(item))
                        {
                            PopupControl.CheckedListBoxControl1.SetItemChecked(i, true);
                            break;
                        }
                    }
                }

                PopupControl.Width = this.Width - this.BaseEdit.Left;
                int count = Math.Max(1, PopupControl.CheckedListBoxControl1.ItemCount);
                count = Math.Min(10, count);
                PopupControl.Height = this.ItemHeight * count + 29;
            }
        }

        /// <summary>
        /// 用于默认的描绘事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks></remarks>
        private void checkedComboBox_CustomDisplayText(object sender, CustomDisplayTextEventArgs e)
        {
            if (e.Value is not null)
            {
                string[] valueCollection = e.Value.ToString().Split(this.SeparatorChar);
                StringBuilder displayText = new StringBuilder();
                if (this.DataSource is not null)
                {
                    if (this.DataSource is DataTable dataTable && !string.IsNullOrEmpty(this.ValueMember))
                    {
                        foreach (DataRow dr in dataTable.Rows)
                        {
                            var item_value = dr[this.ValueMember];
                            if (!valueCollection.Contains(item_value))
                                continue;
                            if (displayText.Length > 0)
                                displayText.Append(this.SeparatorChar);
                            if (!string.IsNullOrEmpty(this.DisplayMember))
                                displayText.Append(dr[this.DisplayMember]?.ToString());
                            else
                                displayText.Append(item_value?.ToString());

                        }
                    }
                    else if (this.DataSource is IEnumerable items)
                    {
                        foreach (object item in items)
                        {
                            if (item is null)
                                continue;
                            object item_value = null;
                            string item_display = null;
                            var members = item.GetType().GetMembers();
                            var member = members.FirstOrDefault(x => (x.Name ?? "") == (this.ValueMember ?? "") && (x is FieldInfo || x is PropertyInfo));
                            if (member is not null)
                            {
                                if (member is FieldInfo field)
                                    item_value = field.GetValue(item);
                                if (member is PropertyInfo property)
                                    item_value = property.GetValue(item);
                            }
                            if (!valueCollection.Contains(item_value))
                                continue;
                            if (!string.IsNullOrEmpty(this.DisplayMember))
                            {
                                member = members.FirstOrDefault(x => (x.Name ?? "") == (this.DisplayMember ?? "") && (x is FieldInfo || x is PropertyInfo));
                                if (member is object)
                                {
                                    if (member is FieldInfo field)
                                        item_display = field.GetValue(item)?.ToString();
                                    if (member is PropertyInfo property)
                                        item_display = property.GetValue(item)?.ToString();
                                }
                            }
                            item_display ??= (item_value?.ToString());
                            if (displayText.Length > 0)
                                displayText.Append(this.SeparatorChar);
                            displayText.Append(item_display);
                        }
                    }
                }
                else if (e.Value is Component component)
                {
                    e.DisplayText = component.Site.Name;
                }
                else if (e.Value.GetType().Attributes == TypeAttributes.Class)
                {
                    e.DisplayText = e.Value.GetType().Name;
                }
                else if (e.Value is Enum)
                {
                    Enum value = (Enum)e.Value;
                    var field = value.GetType().GetField(value.ToString());
                    var attribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false); // 获取描述属性
                    if (attribute.Length > 0)
                    {
                        DescriptionAttribute DescriptionAttribute = (DescriptionAttribute)attribute[0];
                        e.DisplayText = DescriptionAttribute.Description;
                    }
                }
                e.DisplayText = displayText.ToString();
            }
        }

        private bool EqualsValue(object value1, object value2)
        {
            if (value1 is int && value2 is long || value1 is long && value2 is int)
            {
                return value1 == value2;
            }
            else if (value1 is float && value2 is double || value1 is float && value2 is double)
            {
                return value1 == value2;
            }
            else if (value1 is float && value2 is decimal || value1 is float && value2 is decimal)
            {
                return value1 == value2;
            }
            else if (value1 is double && value2 is decimal || value1 is double && value2 is decimal)
            {
                return value1 == value2;
            }
            return false;
        }

        /// <summary>
        /// 值变化之后触发，当前事件是用于在更新开关为false的情况下，同步SelectedItems属性
        /// </summary>
        /// <param name="Sender"></param>
        /// <param name="e"></param>
        /// <remarks></remarks>
        private void BCheckedComboBox_ValueChanged(object Sender, EventArgs e)
        {
            if (this.Updating == false)
            {
                this.SelectedItems.Clear();
                if (!string.IsNullOrEmpty(this.Value))
                {
                    var collection = this.Value.Split(this.SeparatorChar);
                    foreach (string item in collection)
                        this.SelectedItems.Add(item);
                }
            }
        }
    }
}